home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d21
/
dvcron10.arc
/
CRON.C
< prev
next >
Wrap
Text File
|
1991-12-21
|
12KB
|
437 lines
/*
Copyright (c) 1991 -- Kyle A. York
copy / use / modify at will -- see CRON.DOC for details
*/
#include <dir.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <process.h>
#include <fcntl.h>
#include <stdlib.h>
#include <io.h>
#include <tvapi.h>
#include <ctype.h>
#include <sys\stat.h>
#include <alloc.h>
#include "pif.h"
#include "getopt.h"
extern int directvideo=0; /* use BIOS calls for writes */
unsigned _stklen=2048; /* use a 2K stack (not default 4K) */
char *buffer, /* buffer for CRONTAB file. set once at start */
crontabname[MAXPATH], /* full path to 'crontab' */
cronlogname[MAXPATH], /* full path to 'cron.log'*/
crontemplate[MAXPATH]; /* full path to template ".dvp" file */
int bufsize; /* size of input buffer */
time_t now; /* current time */
/*
this function seems to be missing from the DVGLUE library.
it pops-up an error window & displays the message. then it waits
for ESCAPE or a mouse button to be pressed before returning
*/
void DVError(char *fmt, ...)
{
struct REGPACK regs;
OBJECT mytask;
char errmsg[256],
*tmp=errmsg;
va_list ap;
int rows=1;
va_start(ap, fmt);
vsprintf(errmsg, fmt, ap);
va_end(ap);
while (*tmp) /* count # of rows used */
if (*(tmp++) == '\n') /* by message */
rows++;
mytask=TVmytask();
regs.r_bx=0x4000 + 0x2000 + strlen(errmsg);
regs.r_es=FP_SEG(errmsg);
regs.r_di=FP_OFF(errmsg);
regs.r_cx=0x5000 | rows;
regs.r_dx=FP_SEG(mytask);
regs.r_ax=0x101f;
intr(0x15, ®s);
}
/*
write info to log file
(1) open logfile
(2) write info with timestamp
(3) close file
*/
void cronlog(char *fmt, ...)
{
FILE *logfile;
char logstr[256];
va_list ap;
if (!*cronlogname)
return;
va_start(ap, fmt);
vsprintf(logstr, fmt, ap);
va_end(ap);
logfile=fopen(cronlogname, "at");
printf("%24.24s: %s\n", ctime(&now), logstr);
if (logfile) {
fprintf(logfile, "%24.24s: %s\n", ctime(&now), logstr);
fclose(logfile);
} else
fprintf(stderr, "cannot open logfile {%s}\n", cronlogname);
}
/*
read the CRON file if necessary
1st call : open 'crontab'
successive calls : check file time with last read, if updated, reread
note: crontab is open FOR THE DURATION OF THE PROGRAM. it is NEVER closed
*/
void ReadCronFile(void)
{
struct ftime new; /* file time now */
static struct ftime old; /* last file time */
static int handle=-1;
int bytesread;
if (handle < 0) {
old.ft_day=0; /* force new read */
handle=open(crontabname, /* name of file */
O_RDONLY | O_TEXT | O_CREAT, /* used to open normal file */
S_IREAD | S_IWRITE); /* used if file created */
if (handle < 0) { /* if un-openable, abort */
DVError("unable to open crontab file");
exit(1);
} else
cronlog("{%s} opened successfully", crontabname);
}
getftime(handle, &new); /* get timestamp on file */
if (memcmp(&new, &old, sizeof(new))) { /* if unequal, re-read file */
old=new; /* update last read */
cronlog("CRONTAB core updated");
lseek(handle, 0, SEEK_SET); /* rewind file */
bytesread=read(handle, buffer, min(bufsize, filelength(handle)));
buffer[bytesread]=0;
if (filelength(handle) >= bufsize)
cronlog("crontab file overflowed buffer. truncated.");
}
}
/*
skip string ptr over spaces & tabs
cannot use isspace() as it also skips c/r, l/f, f/f and some others
*/
void SkipSpace(char **spc)
{
while ((**spc == ' ') || (**spc == 9))
(*spc)++;
}
/*
skip string ptr over a signed integer
*/
void SkipNum(char **spc)
{
SkipSpace(spc);
if (**spc == '-')
(*spc)++;
while (isdigit(**spc))
(*spc)++;
}
/*
skip string ptr until a space is found
*/
void SkipNonSpc(char **spc)
{
while (**spc && !isspace(**spc))
(*spc)++;
}
/*
given a number list
eg: 1-9,10,12-14
check that a number is included in the list
*/
int IsNumInList(char *s, int num)
{
int lo, hi;
char *list=s;
SkipSpace(&list);
if (*list == '*')
return(TRUE);
while (isdigit(*list)) {
lo=atoi(list);
SkipNum(&list);
if (lo == num)
return(TRUE);
else if (*list == '-') {
list++;
if (!isdigit(*list))
return(FALSE);
hi=atoi(list);
SkipNum(&list);
if ((lo <= num) && (num <= hi))
return(TRUE);
}
if (*list == ',')
list++;
}
return(FALSE);
}
/*
call IsNumInList(), then skip field
*/
int CheckNumInList(char **s, int num)
{
int tmp;
tmp=IsNumInList(*s, num);
SkipNonSpc(s);
SkipSpace(s);
return(tmp);
}
/*
begin a new task
assume preceding flags are checked
this does the extension parsing for how-to-execute
*/
int SpawnPif(char *name, char *parms, int minmem, int maxmem,
int maxexp, int hiddenflag, int backflag)
{
int handle,
size,
t;
DVPtype pif;
OBJECT obj;
char ext[MAXEXT],
tmp[128];
fnsplit(name, NULL, NULL, NULL, ext);
t=(stricmp(ext, ".dvp") == 0);
handle=open(t ? name : crontemplate, O_BINARY | O_RDONLY);
if (handle < 0) {
cronlog("cannot open: %s", t ? name : crontemplate);
return(-1);
}
size=read(handle, &pif, sizeof(pif));
close(handle);
if (minmem >= 0)
pif.minmem=minmem;
if (maxmem >= 0)
pif.maxmem=maxmem;
if (maxexp >= 0)
pif.maxexpanded=maxexp;
if (backflag >= 0)
pif.flags4 |= 0x10;
if (!stricmp(ext, ".com") || !stricmp(ext, ".exe")) {
strcpy(pif.path, name);
pif.autocloseonexit=1;
}
if (!stricmp(ext, ".bat")) {
strcpy(tmp, name);
strcat(tmp, " ");
strcat(tmp, parms);
} else
strcpy(tmp, parms);
if (strlen(tmp) > 63) {
cronlog("parameter string > 63 chars {%s} {%s}", name, parms);
return(-1);
}
strcpy(pif.parameters, tmp);
pif.flags2=0x20 | (*tmp ? 0x40 : 0x00);
obj=DVapp_start(&pif, size);
if (obj && hiddenflag)
TVapp_hide(obj);
if (obj)
cronlog("%s spawned as %08lx", name, obj);
else
cronlog("%s <<SPAWN FAILED>>", name);
return(0);
}
/*
replace all occurences of rep in str with 2-digit val
*/
void Replace(char *str, char *rep, int val)
{
char *ptr, tmp[3];
do {
ptr=strstr(str, rep);
if (ptr) {
sprintf(tmp, "%02d", val);
memcpy(ptr, tmp, 2);
}
} while (ptr);
}
/*
this does the pre-parsing.
*/
void Execute(char *s, struct tm *tm)
{
char cmd[64],
param[64],
*ptr=s,
done=0;
int ii=0,
minmem=-1, /* minimum conventional memory required */
maxmem=-1, /* maximum conventional memory allowed */
maxexp=-1, /* maximum expanded memory allowed */
num, /* temp number for conventional memory */
hiddenflag=0, /* 1 = yes */
backflag=-1; /* 1 = start in background,
0 = start in foreground,
-1 = use default */
do { /* parse for prefixes */
SkipSpace(&ptr);
if (*ptr == '-') {
ptr++;
switch(*(ptr++)) {
case 'b': backflag=1; break;
case 'c': num=atoi(ptr);
SkipNum(&ptr);
if (num < 0)
minmem=-num;
else
maxmem=num;
break;
case 'e': maxexp=atoi(ptr);
SkipNum(&ptr);
break;
case 'h': hiddenflag=1;
break;
default: ptr-=2;
done=1;
break;
}
} else
done=1;
} while (!done);
while (*ptr && !isspace(*ptr) && (ii < 64)) { /* copy command */
cmd[ii++]=*ptr;
ptr++;
}
if (ii >= 64) {
cronlog("program name > 63 characters {%s}", s);
return;
}
cmd[ii]=0;
SkipSpace(&ptr); /* skip spaces */
ii=0; /* everything to end-of-line */
while (*ptr && (*ptr != '\n') && (ii < 64)) { /* are parameters for the command */
param[ii++]=*ptr;
ptr++;
}
if (ii >= 64) {
cronlog("parameters > 63 characters {%s}", s);
return;
}
param[ii]=0;
Replace(param, "%M", tm->tm_mon+1); /* do necessary parameter */
Replace(param, "%D", tm->tm_mday); /* replacements */
Replace(param, "%h", tm->tm_hour);
Replace(param, "%m", tm->tm_min);
SpawnPif(cmd, param, minmem, maxmem, maxexp, hiddenflag, backflag);
}
/*
this is the loop where stuff actually gets done.
it checks the core image to see if anything is ready
to be spawned & sends the necessary data for spawning
*/
void DoCronStuff(struct tm *tm)
{
char *bufptr=buffer,
tmp;
while (*bufptr) {
if (CheckNumInList(&bufptr, tm->tm_min) &&
CheckNumInList(&bufptr, tm->tm_hour)) {
tmp=CheckNumInList(&bufptr, tm->tm_mday);
if (CheckNumInList(&bufptr, tm->tm_mon))
if (CheckNumInList(&bufptr, tm->tm_wday) || tmp)
Execute(bufptr, tm);
}
while ((*bufptr != '\n') && *bufptr)
bufptr++;
if (*bufptr == '\n')
bufptr++;
}
}
void main(int argc, char **argv)
{
struct tm *tm; /* structure for more readable time */
OBJECT timer; /* TV timer object */
char drive[MAXDRIVE], /* path to CRON.EXE */
dir[MAXDIR];
int key,
errflag;
DVinit(); /* initialize DV functions */
bufsize=1024;
fnsplit(argv[0], drive, dir, NULL, NULL);
fnmerge(crontabname, drive, dir, "crontab", NULL);
fnmerge(cronlogname, drive, dir, "cron", ".log");
fnmerge(crontemplate, drive, dir, "crondos", ".dvp");
errflag=0;
while ((key=getopt(argc, argv, "c:d:l:m:")) != EOF) {
switch(key) {
case 'c': strcpy(crontabname, optarg); break;
case 'd': strcpy(crontemplate, optarg); break;
case 'l': if (!stricmp(optarg, "-"))
*cronlogname=0;
else
strcpy(cronlogname, optarg);
break;
case 'm': bufsize=atoi(optarg);
break;
default: errflag=1;
break;
}
}
if (errflag) {
DVError("format:\n\r %s [-c crontabname] [-d crontemplate] [-l-] "
"[-l logfilename] [-m memsize]",
argv[0]);
exit(1);
}
printf("Buffer size: %d\n", bufsize);
printf("CRONTAB: %s\n", crontabname);
printf("Log file: %s\n", cronlogname);
printf("Template: %s\n", crontemplate);
if (!(buffer=malloc(bufsize))) { /* allocate buffer */
DVError("Could not allocate CRONTAB buffer");
exit(1);
}
if (access(crontemplate, 0)) { /* check that template */
DVError("Template not found {%s}", crontemplate); /* exists */
exit(1);
}
timer=TVtimer_new(); /* initialize timer */
do {
time(&now); /* get current time */
tm=localtime(&now); /* in structure */
TVtimer_begin(timer, 100*(60-tm->tm_sec)); /* start countdown until
next minute */
ReadCronFile(); /* load the CRON file */
DoCronStuff(tm); /* execute instructions */
TVtimer_wait(timer); /* give-up CPU until
counter reaches 0 */
} while (1); /* repeat indefinetly */
}